﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Web.UI.WebControls;
using Frame.Lib.Enums;
using Frame.Lib.Common;
using Frame.Lib.Utilities;

namespace Frame.Lib.Core.Tree
{
    public class TreeBO<Info> : TreeDAL<Info> where Info : TreeInfo,new()
    {
        private const int IMG_WIDTH = 11;
        private const int SPACE_WIDTH = 20;
        public TreeBO(string tableName)
            : base(tableName)
        {
        }

        public override void Delete(IEnumerable<int> ids)
        {
            List<int> lstSubIDs = GetSubIDs(ids);
            base.Delete(lstSubIDs);
        }

        #region 把源表整理成树状列表输出
        ///// <summary>
        ///// 把源表整理成树状列表输出
        ///// </summary>
        ///// <param name="dtSrc"></param>
        ///// <returns></returns>
        //public IEnumerable<Info> GetTreeList(IEnumerable<Info> src)
        //{
        //    List<Info> dest = new List<Info>();
        //    SetTree(dest, src.ToList(), Jzy.Common.Constants.TREE_ROOT_ID);
        //    return dest;
        //}

        //public virtual IEnumerable<Info> GetTreeList()
        //{
        //    IEnumerable<Info> src = GetList();

        //    return GetTreeList(src);

        //}

        //private void SetTree(List<Info> dest, List<Info> src, int upperID)
        //{
        //    string strSpace = "&nbsp;&nbsp;&nbsp;&nbsp;";

        //    Type type = typeof(Info);



        //    IEnumerable<Info> tmp = from info in src
        //                            where (int)type.GetProperty("UpperID").GetValue(info, null) == upperID
        //                            orderby (int)type.GetProperty("Orders").GetValue(info, null)
        //                            select info;
        //    foreach (Info info in tmp)
        //    {
        //        dest.Add(info);

        //        int id = (int)type.GetProperty("ID").GetValue(info, null);
        //        int depth = (int)type.GetProperty("Depth").GetValue(info, null);
        //        string strTab = "";//缩进
        //        for (int i = 0; i < depth; i++)
        //        {
        //            strTab += strSpace;
        //        }

        //        int subCount = (from tree in src
        //                        where type.GetProperty("Path").GetValue(tree, null).ToString().IndexOf("," + id + ",") >= 0
        //                        select tree).Count();
        //        if (subCount > 0)
        //        {
        //            if (strTab.Length > 0)
        //            {
        //                strTab = strTab.Substring(0, strTab.Length - 12);//给折叠符号留出一点空间
        //            }
        //            strTab += "<img src='" + Jzy.Utility.GlobalVar.WebAppPath + "images/Tree/-.jpg' style='cursor:hand' border='0' onclick='Collapse(" + dest.Count + "," + subCount + ")' />&nbsp;";
        //        }

        //        type.GetProperty("Space").SetValue(info, strTab, null);
        //        SetTree(dest, src, id);
        //    }
        //}
        #endregion

        #region 把源表整理成树状列表输出
        /// <summary>
        /// 把源表整理成树状列表输出
        /// </summary>
        /// <param name="dtSrc"></param>
        /// <param name="webAppPath">从webservice调用时路径要传过来</param>
        /// <returns></returns>
        public List<Info> GetTreeList(List<Info> src, string webAppPath)
        {
            List<Info> dest = new List<Info>();
            //dtDest.Columns.Add("Space");
            //dtDest.Columns.Add("HasChild", typeof(bool));
            SetTree(dest, src, Constants.TREE_ROOT_UPPER_ID, webAppPath);
            return dest;
        }

        public virtual List<Info> GetTreeList()
        {
            return GetTreeList(GlobalVar.WebAppPath);
        }

        
        public virtual List<Info> GetTreeList(int rootID)
        {
            List<Info> src = base.GetTreeList(rootID);
            List<Info> dest = new List<Info>();
            //dtDest.Columns.Add("Space");
            //dtDest.Columns.Add("HasChild", typeof(bool));
           
            SetTree(dest, src,Constants.TREE_ROOT_UPPER_ID , GlobalVar.WebAppPath);
            return dest;
        }

        public virtual List<Info> GetTreeList(string webAppPath)
        {
            List<Info> list = base.GetList();
            return GetTreeList(list, webAppPath);
        }

        private void SetTree(List<Info> dest, List<Info> src, int upperID, string webAppPath)
        {
           
            //DataView dv = new DataView(dtSrc);
            //dv.RowFilter = "UpperID=" + upperID;
            //dv.Sort = "Orders";

            IEnumerable<Info> nodes = src.Where(T => T.UpperID == upperID).OrderBy(T => T.Orders);

            foreach (Info info in nodes)
            {
               // DataRow dr = dtDest.NewRow();

                //Info newNode = new Info();

                //for (int i = 0; i < dtSrc.Columns.Count; i++)//复制原来列里面的所有内容
                //{
                //    dr[i] = drv[i];
                //}

                //DataView dvTmp = new DataView(dtSrc);
                //dvTmp.RowFilter = "Path like '%," + info.ID + ",%'";
                IEnumerable<Info> tmpNodes = src.Where(T => T.Path.Contains("," + info.ID + ","));

                //int layer = info.Depth;

                int padding = info.Depth * SPACE_WIDTH + IMG_WIDTH;

                string strImg = "";
                if (tmpNodes.Count() > 0)//子节点大于0个则加上折叠图片Collapse(RowIndex,SubRows)
                {
                    padding = padding - IMG_WIDTH; ;//给折叠符号留出一点空间  

                    strImg = "<img src='" + webAppPath + "common/images/Tree/-.jpg' style='cursor:pointer' border='0' onclick='Collapse(" + (dest.Count + 1) + "," + tmpNodes.Count() + ")' />";
                    info.HasChild = true;
                    //dr["HasChild"] = true;
                }
                else
                {
                    //dr["HasChild"] = false;
                    info.HasChild = false;
                }
                info.Space = "<span style='margin-right:" + padding + "px;cursor:default;'>&nbsp;</span>" + strImg;

                dest.Add(info);

                //dtDest.Rows.Add(dr);
                SetTree(dest, src, info.ID, webAppPath);
            }
        }
        #endregion

        #region 根据外面提供的数据绑定到TreeView上
        /// <summary>
        /// 根据外面提供的数据绑定到TreeView上
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="dt"></param>
        public void BindTreeView(TreeView tv, IEnumerable<Info> trees, bool haveCheckBox, List<int> lstSelectIDs)
        {
            BindTreeView(tv, trees, haveCheckBox, 0,lstSelectIDs);
        }

        public void BindTreeView(TreeView tv, IEnumerable<Info> trees, bool haveCheckBox, int upperID, List<int> lstSelectIDs)
        {
            tv.ShowLines = true;
            tv.Nodes.Clear();

            if (haveCheckBox)
            {
                tv.ShowCheckBoxes = TreeNodeTypes.All;
            }
            JSUtil.SetTreeSelect(lstSelectIDs);
            tv.EnableViewState = false;
            tv.CssClass = "treeview";
            GetNode(tv, trees, null, upperID,lstSelectIDs);
        }

        public virtual void BindTreeView(TreeView tv, bool haveCheckBox, List<int> lstSelectIDs)
        {
            BindTreeView(tv, haveCheckBox, Constants.TREE_ROOT_UPPER_ID,lstSelectIDs);
        }

        public virtual void BindTreeView(TreeView tv, bool haveCheckBox, int upperID, List<int> lstSelectIDs)
        {
            List<Info> trees = base.GetList();
            BindTreeView(tv, trees, haveCheckBox, upperID, lstSelectIDs);
        }


        private void GetNode(TreeView tv, IEnumerable<Info> trees, TreeNode node, int upperID, List<int> lstSelectIDs)
        {           

            IEnumerable<Info> subTrees = trees.Where(T => T.UpperID == upperID).OrderBy(T => T.Orders);          

            foreach (TreeInfo info in subTrees)
            {
                TreeNode nodeTmp = new TreeNode();          

                nodeTmp.Text = nodeTmp.ToolTip = info.Name;
                nodeTmp.Value = info.ID.ToString();

                if (info.ShowCheckBox != null)
                {
                    nodeTmp.SelectAction = TreeNodeSelectAction.None;
                    nodeTmp.ShowCheckBox = info.ShowCheckBox;
                }
                else if (tv.ShowCheckBoxes == TreeNodeTypes.All)
                {
                    nodeTmp.ShowCheckBox = true;
                }
               

                if (lstSelectIDs != null)
                {
                    if (lstSelectIDs.Contains(info.ID))
                    {
                        ExpendNode(node);
                    }
                }

                if (nodeTmp.ShowCheckBox == true)
                {
                    nodeTmp.SelectAction = TreeNodeSelectAction.None;
                    nodeTmp.Text = GetCheckBoxNode(info.ID, info.Name, upperID);
                    nodeTmp.ShowCheckBox = false;
                }

               

                if (node == null)
                {
                    tv.Nodes.Add(nodeTmp);
                }
                else
                {
                    node.ChildNodes.Add(nodeTmp);
                }
                GetNode(tv, trees, nodeTmp, info.ID,lstSelectIDs);
            }
        }

        public static void ExpendNode(TreeNode node)
        {
            if (node != null)
            {
                node.Expand();
                ExpendNode(node.Parent);
            }
        }
        #endregion

        #region 判断目标ID是否包含在源及源目录当中的所有子目录当中
        /// <summary>
        /// 判断目标ID是否包含在源及源目录当中的所有子目录当中
        /// </summary>
        /// <param name="lstSrcIDs"></param>
        /// <param name="iDestID"></param>
        /// <returns></returns>
        public bool Include(IEnumerable<int> lstSrcIDs, int destID)
        {
            List<int> lstSubIDs = GetSubIDs(lstSrcIDs);
            if (lstSubIDs.IndexOf(destID) > -1)
            {
                return true;
            }
            else
            {
                return false;
            }
        }
        #endregion

        #region 还原TreeView的Checkbox的选择状态
        /// <summary>
        /// 还原TreeView的Checkbox的选择状态
        /// </summary>
        /// <param name="tvList"></param>
        /// <param name="lstSelectIDs"></param>
        public static void SetSelect(TreeView tvList, List<int> lstSelectIDs)
        {
            foreach (TreeNode node in tvList.Nodes)
            {
                SetSelect(node, lstSelectIDs);
            }
        }

        public static void SetSelect(TreeNode node, List<int> lstSelectIDs)
        {
            int tmp = int.Parse(node.Value);
            if (lstSelectIDs.Contains(tmp))
            {
                node.Checked = true;
                if (node.Parent != null)
                {
                    node.Parent.Expand();
                }
            }
            foreach (TreeNode nodeTmp in node.ChildNodes)
            {
                SetSelect(nodeTmp, lstSelectIDs);
            }
        }
        #endregion


        #region 生成做导航用的树
        /// <summary>
        /// 生成做导航用的树
        /// </summary>
        /// <param name="tv"></param>
        /// <param name="dt">调用时可传入null值</param>
        /// <param name="node">调用时可传入null值</param>
        /// <param name="upperID"></param>
        /// <param name="navigateUrl"></param>
        public void BindTreeView(TreeView tv, List<Info> list, TreeNode node, int upperID, string navigateUrl)
        {
            if (list == null)
            {
                list = base.GetList();
            }

            IEnumerable<Info> subTrees = list.Where(T => T.UpperID == upperID).OrderBy(T => T.Orders);

      
            tv.CssClass = "treeview";

            foreach (Info row in subTrees)
            {
                TreeNode nodeTmp = new TreeNode();
                nodeTmp.Text = row.Name;
                nodeTmp.ToolTip = nodeTmp.Text;
                nodeTmp.Value = row.ID.ToString();

                nodeTmp.NavigateUrl = navigateUrl + StrUtil.EncryptUrl(nodeTmp.Value);

                if (node == null)
                {
                    tv.Nodes.Add(nodeTmp);
                }
                else
                {
                    node.ChildNodes.Add(nodeTmp);
                }

                BindTreeView(tv, list, nodeTmp, row.ID, navigateUrl);
            }
        }
        #endregion

        #region 还原节点展开状态
        /// <summary>
        /// 还原节点展开状态
        /// </summary>
        /// <param name="tvModule"></param>
        /// <param name="lstExpendIDs"></param>
        public static void RestoreExpend(TreeView tvModule, List<string> lstExpendIDs)
        {
            foreach (TreeNode node in tvModule.Nodes)
            {
                RestoreExpend(node, lstExpendIDs);
            }
        }

        private static void RestoreExpend(TreeNode node, List<string> lstExpendIDs)
        {
            if (lstExpendIDs.IndexOf(node.Value) >= 0)
            {
                node.Expand();
            }

            foreach (TreeNode nodeTmp in node.ChildNodes)
            {
                RestoreExpend(nodeTmp, lstExpendIDs);
            }
        }
        #endregion

        #region 把节点展开状态保存到集合中去
        /// <summary>
        /// 把节点展开状态保存到集合中去
        /// </summary>
        /// <param name="tvModule"></param>
        /// <param name="lstExpendIDs"></param>
        public static void SetExpend(TreeView tvModule, List<string> lstExpendIDs)
        {
            foreach (TreeNode node in tvModule.Nodes)
            {
                SetExpend(node, lstExpendIDs);
            }
        }

        private static void SetExpend(TreeNode node, List<string> lstExpendIDs)
        {
            if (node.Expanded == true)
            {
                lstExpendIDs.Add(node.Value);
            }

            foreach (TreeNode nodeTmp in node.ChildNodes)
            {
                SetExpend(nodeTmp, lstExpendIDs);
            }
        }
        #endregion


        #region 生成带CheckBox的节点
        /// <summary>
        /// 生成带CheckBox的节点
        /// </summary>
        /// <param name="value"></param>
        /// <param name="text"></param>
        /// <param name="upperID">如没有可为null</param>
        /// <returns></returns>
        public static string GetCheckBoxNode(object value, object text, object upperID)
        {
            string node = "<input id=\"_" + value + "\" name=\"_" + value + "\" type=\"checkbox\" ";
            if(upperID!=null)
            {
                node += "upperid=\"_" + upperID + "\" ";
            }
            node +="onclick=\"selectIDName(this);\" /><label for=\"_" + value + "\">" + text + "</label>";
            return node;
        }
        #endregion
    }
}
